﻿using mozhi.smarterp.BasicData.Products.Repositories;
using mozhi.smarterp.BasicData.Products.Services;
using mozhi.smarterp.BasicData.Units;
using Org.BouncyCastle.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;

namespace mozhi.smarterp.BasicData.Products
{
    public class ProductAuxiliaryUnitAppService : BasicDataAppService, IProductAuxiliaryUnitAppService
    {
        private IProductAuxiliaryUnitRepository _repository;
        private ProductAuxiliaryUnitManager _manager;
        private IUnitRepository _unitRepository;
        private IProductRepository _productRepository;

        public ProductAuxiliaryUnitAppService(IProductAuxiliaryUnitRepository repository, ProductAuxiliaryUnitManager manager , 
            IUnitRepository unitRepository, IProductRepository productRepository)
        {
            _repository = repository;
            _manager = manager;
            _unitRepository = unitRepository;
            _productRepository = productRepository;
        }

        public async Task<ProductAuxiliaryUnitDto> CreateAsync(ProductAuxiliaryUnitCreateDto input)
        {
            var auxiliaryUnit = await _manager.GetAsync(null, input.ProductId, input.Type, input.OtherUnitId, input.ConversionRate , input.Activated);

            auxiliaryUnit = await _repository.InsertAsync(auxiliaryUnit);

            var result = ObjectMapper.Map<ProductAuxiliaryUnit , ProductAuxiliaryUnitDto>(auxiliaryUnit);

            await LoadOtherInfoAsync(new List<ProductAuxiliaryUnitDto> { result });

            return result;
        }

        public async Task DeleteAsync(Guid id)
        {
            var auxiliaryUnit = await _repository.GetAsync(id);

            if (auxiliaryUnit == null)
                throw new UserFriendlyException($"产品单位换算：{id}不存在", "100000");

            await _repository.DeleteAsync(id);
        }

        public async Task<ProductAuxiliaryUnitDto> GetAsync(Guid id)
        {
            var auxiliaryUnit = await _repository.GetAsync(id);

            var result = ObjectMapper.Map<ProductAuxiliaryUnit, ProductAuxiliaryUnitDto>(auxiliaryUnit);

            await LoadOtherInfoAsync(new List<ProductAuxiliaryUnitDto> { result });

            return result;
        }

        public async Task<PagedResultDto<ProductAuxiliaryUnitDto>> GetListAsync(ProductAuxiliaryUnitResultRequestDto filter)
        {
            ProductAuxiliaryUnit selft = null;

            if (filter.IncludeItSelf && filter.ProductId.HasValue)
            {
                var product = await _productRepository.GetAsync(filter.ProductId.Value);
                if (product != null)
                    selft = new ProductAuxiliaryUnit(product.Id, product.Id, Enums.AuxiliaryUnitRateType.FixedValue, product.BasicUnitId, product.BasicUnitId, 1, true);
            }

            var auxiliaryUnits = await _repository.GetPagedListAsync(filter.ProductId , filter.OtherUnitId , filter.SkipCount, filter.MaxResultCount, filter.Sorting);

            var count = await _repository.GetCountAsync(filter.ProductId, filter.OtherUnitId);

            var result = new PagedResultDto<ProductAuxiliaryUnitDto>();

            if (selft != null)
            {
                auxiliaryUnits.Insert(0, selft);
                count = count + 1;
            };

            result.Items = ObjectMapper.Map<List<ProductAuxiliaryUnit>, List<ProductAuxiliaryUnitDto>>(auxiliaryUnits);
            result.TotalCount = count;

            await LoadOtherInfoAsync((List<ProductAuxiliaryUnitDto>)result.Items);

            return result;
        }

        public async Task<ProductAuxiliaryUnitDto> UpdateAsync(ProductAuxiliaryUnitUpdateDto input)
        {
            var auxiliaryUnit = await _manager.GetAsync(input.Id, input.ProductId, input.Type, input.OtherUnitId, input.ConversionRate, input.Activated);

            auxiliaryUnit = await _repository.UpdateAsync(auxiliaryUnit);

            var result = ObjectMapper.Map<ProductAuxiliaryUnit, ProductAuxiliaryUnitDto>(auxiliaryUnit);

            await LoadOtherInfoAsync(new List<ProductAuxiliaryUnitDto> { result });

            return result;
        }

        #region
        private async Task LoadOtherInfoAsync(List<ProductAuxiliaryUnitDto> auxiliaryUnits)
        {
            if (auxiliaryUnits == null || auxiliaryUnits.Count == 0)
                return;

            foreach (var auxiliaryUnit in auxiliaryUnits)
            {
                var product = await _productRepository.GetAsync(auxiliaryUnit.ProductId);
                var basicUnit = await _unitRepository.GetAsync(auxiliaryUnit.BasicUnitId);
                var otherUnit = await _unitRepository.GetAsync(auxiliaryUnit.OtherUnitId);

                auxiliaryUnit.BasicUnitName = basicUnit?.Name;
                auxiliaryUnit.OtherUnitName = otherUnit?.Name;
                auxiliaryUnit.ProductCode = product?.Code;
                auxiliaryUnit.ProductName = product?.Name;
            }
        }
        #endregion
    }
}
